#!/usr/bin/env python
#
# Copyright 2013 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""An app to receive and display data from WiFi Testing Devices."""
__author__ = "Joey Freeland (joeyfreeland@gmail.com)"

from datetime import datetime

import json
import webapp2

import models
import tools

from google.appengine.ext import db
from google.appengine.api import users

SOFTWARE_VERSION = "0.0.7"
SOFTWARE_FILES = ["main.py,http://app-website/files/main.py.txt,"
                  "/home/pi/main.py",
                  "device.py,http://app-website/files/device.py.txt,"
                  "/home/pi/device.py",
                  "network.py,http://app-website/files/network.py.txt,"
                  "/home/pi/network.py",
                  "web.py,http://app-website/files/web.py.txt,"
                  "/home/pi/web.py"]


class AddTestResult(webapp2.RequestHandler):
  """Save the results in the database."""

  def post(self):
    """Create a TestResult instance and assign values."""
    r = self.request
    t = models.TestResult()
    attributes = self.request.arguments()
    attributes.remove("date")
    t.date = datetime.utcnow()
    for a in attributes:
      t.__setattr__(a, r.get(a))
    try:
      query = (db.Query(models.TestResult)
               .filter("location = ", r.get("location"))
               .filter("provider = ", r.get("provider"))
               .order("-date"))
      last_update_time = query.get()
      if last_update_time:
        tslr = datetime.utcnow() - last_update_time.date
        t.time_since_last_result = str(tslr.seconds)
    except:
      pass
    t.put()
    self.response.out.write("TestResult written to data store.")


class CheckRedirect(webapp2.RequestHandler):
  """Allow a device to check to see if there's a redirect."""

  def get(self):
    self.response.out.write("You were not redirected.")


class DeviceCheckIn(webapp2.RequestHandler):
  """Accept a new device and generate a new config if there are updates."""

  def post(self):
    r = self.request
    mac_address = r.get("mac_address")
    query = db.Query(models.WiFiTestingDevice).filter("mac_address = ",
                                                      mac_address)
    device = query.get()
    if device:
      if (device.config_version == r.get("config_version") and
          device.software_version == r.get("software_version")):
        device.last_update = datetime.now()
        device.save()
        self.response.out.write("Up to date.")
      elif (device.config_version == r.get("config_version") and
            device.software_version != r.get("software_version")):
        device.last_update = datetime.now()
        device.software_version = r.get("software_version")
        device.save()
        self.response.out.write("Updated.")
      else:
        config = {}
        config["config_version"] = device.config_version
        config["device_name"] = device.device_name
        config["local_speedtest_name"] = device.local_speedtest_name
        config["local_speedtest_url"] = device.local_speedtest_url
        config["mac_address"] = device.mac_address
        config["provider"] = device.provider
        config["remote_speedtest_name"] = device.remote_speedtest_name
        config["remote_speedtest_url"] = device.remote_speedtest_url
        config["ssh_host"] = device.ssh_host
        config["ssh_port"] = device.ssh_port
        config["ssh_user"] = device.ssh_user
        device.last_update = datetime.now()
        device.save()
        self.response.out.write(json.dumps(config))
    else:
      new = models.WiFiTestingDevice()
      new.config_version = r.get("config_version")
      new.date_added = datetime.now()
      new.device_name = r.get("device_name")
      new.last_update = datetime.now()
      new.local_speedtest_name = r.get("local_speedtest_name")
      new.local_speedtest_url = r.get("local_speedtest_url")
      new.mac_address = r.get("mac_address")
      new.provider = r.get("provider")
      new.remote_speedtest_name = r.get("remote_speedtest_name")
      new.remote_speedtest_url = r.get("remote_speedtest_url")
      new.software_version = r.get("software_version")
      new.put()
      self.response.out.write("Device added.")


class DisplayCurrentVersion(webapp2.RequestHandler):
  """Display the current version of the script."""

  def post(self):
    """Checks the key provided and returns the current version."""
    their_key = self.request.get("key")
    # TODO(joeyfreeland): There must be a better way.
    my_key = "abcdefghijklmnopqrstuvwxyz"
    if their_key == my_key:
      self.response.out.write("%s" % SOFTWARE_VERSION)
    else:
      self.response.out.write("None")


class DisplayFileList(webapp2.RequestHandler):
  """Display the list of files that an out of date script should download."""

  def post(self):
    """Checks the key provided and returns the file list."""
    their_key = self.request.get("key")
    my_key = "abcdefghijklmnopqrstuvwxyz"
    if their_key == my_key:
      for module in SOFTWARE_FILES:
        self.response.out.write("%s\n" % module)
    else:
      self.response.out.write("None")


class GetIP(webapp2.RequestHandler):
  """Return the IP address of the device back to itself."""

  def get(self):
    """Print out the user's IP address."""
    ip = self.request.remote_addr
    self.response.out.write("%s" % ip)


class MainPage(webapp2.RequestHandler):
  """Display nothing."""

  def get(self):
    """Print out the main page."""
    # TODO(joeyfreeland): Come back and make this an attractive start page that
    # talks about Wi-Fi testing, what this suite is, what it does, and why it
    # matters.
    self.response.out.write("")


class UpdateValues(webapp2.RequestHandler):
  """Update all values in the database that have a zero value with a Null."""

  def get(self):
    user = users.get_current_user()
    authorized_user = tools.ValidateUser(user)
    if authorized_user: pass
    else: self.response.out.write("Access denied.")
    results = models.TestResult.all()
    for r in results:
      for p in r.properties():
        if getattr(r, p) == 0:
          setattr(r, p, None)
    self.response.out.write("Done updating all values.")


app = webapp2.WSGIApplication([("/", MainPage),
                               ("/addtestresult", AddTestResult),
                               ("/check_redirect", CheckRedirect),
                               ("/checkin", DeviceCheckIn),
                               ("/filelist", DisplayFileList),
                               ("/getip", GetIP),
                               ("/version", DisplayCurrentVersion),
                               ("/updatevalues", UpdateValues),
                              ],
                              debug=True)


def main():
  app.run()


if __name__ == "__main__":
  main()
